home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
asm
/
alib11b.zip
/
CODE1.ZIP
/
DISPGRAP
/
SPRINT.ASM
< prev
next >
Wrap
Assembly Source File
|
1992-03-09
|
25KB
|
747 lines
page 64,132
;========================================================================
; SPRINTER
; Cursor Speedup Program
; Written 1992 by Douglas Boling
;========================================================================
;========================================================================
; BIOS_DATA segment
;========================================================================
bios_data segment at 40h
org 17h
bios_shift_stat db ? ;Shift status of keyboard
org 1ah
keybuff_head dw ? ;Pointer to first entry in
org 1ch ; BIOS keyboard buffer.
keybuff_tail dw ? ;Pointer to last entry in
org 80h ; BIOS keyboard buffer.
keybuff_start dw ? ;Pointer to beginning of
org 82h ; BIOS keyboard buffer.
keybuff_end dw ? ;Pointer to end of BIOS
org 96h ; keyboard buffer.
kb_status db ? ;Status of keyboard
bios_data ends
;========================================================================
; Code segment (code and data)
;========================================================================
code segment para public'code'
assume cs:code
org 2ch
env_seg dw ? ;Pointer to environment seg
org 80h
command_tail db ?
org 100h
begin: jmp initialize
program db 13,10,"Sprinter 1.0 "
copyright db "Copyright (c) 1992 Douglas Boling",13,10
db "First published in PC Magazine, May 26, 1992",13,10
db "For help type: sprinter /?",13,10
db 13,10,"$",1Ah
;------------------------------------------------------------------------
; Memory locations required for program.
;------------------------------------------------------------------------
enable_flag db 1 ;1 = enabled, 0 = disabled
shift_status db 0 ;bits represent shift status
last_code db 0 ;Previous scan code
cursor_code dw 0 ;Cursor code currently active
shift_mask db 11h ;Activate using Alt keys
make_kept db 0 ;key not passed to BIOS
key_count db 2 ;Number of keys pushed/int
scanlist_ptr label dword ;Pointer to list of scan codes
dw offset scanlist ;Offset
dw ? ;Segment
scanlist db 48h,4bh,4dh,50h,49h,51h ;Cursor key scancodes
shiftlist db 38h,1dh,2ah,36h ;Alt, Ctl, and L/R shift codes
scanlist_end = $
environment_flg db 1 ;1 = environment still owned
int8h dd ? ;int 8h vector (Timer)
int9h dd ? ;int 9h vector (Keyboard)
;========================================================================
; TIMERINT receives control when an interrupt 8 is generated.
;========================================================================
timerint proc far
assume cs:code,ds:nothing,es:nothing
pushf
call cs:[int8h] ;Go to BIOS routine
cmp cs:enable_flag,0 ;See if program enabled
je timer_exit1 ;No, exit
push ax
mov al,cs:shift_status ;See if shift combination
mov ah,cs:shift_mask
test al,ah
je timer_exit ;No, exit
not ah ;See if any other shift key
and al,ah ; is active.
mov ax,cs:cursor_code ;Get saved cursor key code
or ax,ax ;See if cursor key active
je timer_exit ;No, exit
;------------------------------------------------------------------------
;If shift combination set and cursor key pressed, put scancode into buffer.
;------------------------------------------------------------------------
push ds ;Yes, Save registers needed
push bx ; for keyboard buffer work.
push cx
push di
mov bx,40h ;DS = BIOS data segment
mov ds,bx
assume ds:bios_data
cli ;No ints when loading buffer
mov bx,keybuff_tail ;Get pointer to end of buffer
mov di,bx ;Copy to see if buffer full
xor ch,ch
mov cl,cs:key_count ;Get num of keys to push
timer0:
call advance_keyptr ;Check ahead in buffer.
jc timer1 ;If full, goto end
mov [bx],ax ;Put character in queue
mov bx,di ;Update pointer
loop timer0
timer1:
mov keybuff_tail,bx ;Save updated keyboard ptr
sti ;Allow interrupts
pop di ;Restore registers
pop cx
pop bx
pop ds
timer_exit:
pop ax
timer_exit1:
iret ;Return
timerint endp
;========================================================================
; KEYBINT receives control when an interrupt 9 is generated.
;========================================================================
keybint proc far
assume cs:code,ds:nothing,es:nothing
push ax
cmp cs:enable_flag,0 ;See if enabled. If not jump
je go_kb_int1 ; directly to BIOS.
in al,64h ;Read keyboard status port.
test al,1 ;See if output buffer full.
je go_kb_int1 ;No, must be some other I/O.
push cx
push di
push ds
mov ax,cs
mov ds,ax ;DS = CS
assume ds:code
in al,60h ;Read keyboard data port.
sti ;Enable interrupts
;------------------------------------------------------------------------
;Compare scan code with list of keys.
;------------------------------------------------------------------------
push es
les di,scanlist_ptr ;Point to list of scan codes.
mov cx,offset scanlist_end - offset scanlist
mov ah,al ;Copy scan code
and al,7fh ;Remove break bit from code
cld
repne scasb ;Scan list
pop es
jne go_kb_int ;Scancode not in list go BIOS
sub cx,offset scanlist_end - offset scanlist
neg cx ;Make positive
sub cl,offset shiftlist - offset scanlist + 1
jb cursorkey_found ;If first 6 codes, cursor code
;------------------------------------------------------------------------
;Shift key scancode. Set or clear bit in shift status.
;------------------------------------------------------------------------
cmp last_code,0e0h ;See if extended code
jne shiftkey1 ;If extended, increase shift
add cl,4 ; for right alt or ctl keys.
shiftkey1:
mov al,1 ;Use al as a bit set register
shl al,cl ;Shift bit by index into list
test ah,80h ;See if make or break code
jne shiftkey_break ;Break, jump.
or shift_status,al ;Make, set bit in shift status
jmp short go_kb_chk ;Goto BIOS
shiftkey_break:
push ax
not al ;Invert mask to clear bit
and shift_status,al ;Clear bit
pop ax
;------------------------------------------------------------------------
;If proper accelerator shift key, don't pass key to BIOS
;------------------------------------------------------------------------
go_kb_chk:
test al,shift_mask ;If this is the proper
je go_kb_int ; shift and a cursor key
cmp cursor_code,0 ; is down, don't pass scan
je go_kb_int ; code to BIOS.
test ah,80h ;See if make or break
jne go_kb_chk1
mov make_kept,1 ;Indicate make code kept
jmp short go_kb_int
jmp short keyb_iret
go_kb_chk1:
mov make_kept,0 ;Clear flag.
;------------------------------------------------------------------------
;Exit to BIOS keyboard interrupt routine.
;------------------------------------------------------------------------
go_kb_int:
mov last_code,ah ;Save current code
pop ds ;Restore registers
pop di
pop cx
go_kb_int1:
pop ax
jmp cs:[int9h] ;Go to BIOS routine
;------------------------------------------------------------------------
;Discard key. Reset the keyboard and signal end-of-interrupt to the 8259
;------------------------------------------------------------------------
keyb_iret:
call reset_keyboard ;Reset keyboard
mov last_code,ah ;Save current code
pop ds ;Restore registers
pop di
pop cx
pop ax
iret ;Return to program
;------------------------------------------------------------------------
;Cursor key scancode, check for extended key or number key and numlock on.
;------------------------------------------------------------------------
cursorkey_found:
xor al,al ;Assume 0 extended scancode
cmp last_code,0e0h ;See if extended key
jne cursorkey_numpad
mov al,0e0h ;Load extended keycode.
jmp short cursorkey1
cursorkey_numpad:
push es
push ax
mov ax,40h ;ES = BIOS data segment
mov es,ax
assume es:bios_data
pop ax
test es:bios_shift_stat,20h ;See if numlock active
pop es
assume es:nothing
jne go_kb_int ;If so, not a cursor key.
;------------------------------------------------------------------------
;Check for break code. If break, clear stored scan code.
;------------------------------------------------------------------------
cursorkey1:
test ah,80h ;See if break
je cursorkey_make ;No, continue
xor ax,ax ;Yes, clear last code
cursorkey_make:
mov cursor_code,ax ;Save cursor code
mov al,shift_status ;See if shift combination
test shift_mask,al
jne keyb_iret
jmp go_kb_int ;Yes, goto BIOS
keybint endp
;========================================================================
; ADVANCE KEYPTR moves the keyboard buffer pointer to the next free
; location in the BIOS keyboard buffer.
; Entry: DI - keyboard head pointer
; Exit: CF - Set if keyboard buffer full
;========================================================================
advance_keyptr proc near
assume cs:code,ds:bios_data
inc di ;Point to next entry
inc di
cmp di,keybuff_end ;See if at the end of the
jne advance1 ; buffer. If so, reset the
mov di,keybuff_start ; pointer to the start.
advance1:
cmp di,keybuff_head ;See if the buffer is full
je advance_full
clc
jmp short advance_exit
advance_full:
stc
advance_exit:
ret
advance_keyptr endp
;========================================================================
; RESET KEYBOARD resets the interrupts controller. Used when discarding
; scan codes.
;========================================================================
reset_keyboard proc near
push ax
cli ;Disable interrupts
in al,61h ;Reset the keyboard
mov ah,al ; controller
or al,80h
out 61h,al
mov al,ah
out 61h,al
mov al,20h ;Signal end-of-interrupt to
out 20h,al ; the interrupt controller
sti ;Enable interrupts
pop ax
ret
reset_keyboard endp
end_of_code = $
;========================================================================
; End of nonresident code.
;========================================================================
infomsg1 db "The available commands are:"
db 13,10,"/e Enable acceleration"
db 13,10,"/d Disable acceleration"
db 13,10,"/u Uninstall program"
db 13,10,"/s x Set acceleration speed where x"
db " is between 1 and 9"
db 13,10,"/k xx Set shift key where xx is one of"
db " the following:"
db 13,10," a Alt key"
db 13,10," c Ctl key"
db 13,10," s Shift key"
db 13,10," lx to specify only the left key"
db 13,10," rx to specify only the right key"
db 13,10,"/? Print this message$"
infomsg2 db "Sprinter removed$"
infomsg3 db "Sprinter installed",13,10,"$"
infomsg4 db "Acceleration key is "
keytag db 15 dup (" "),13,10
db "Acceleration speed is "
speedtag db 2 dup (" "),13,10,10,"$"
errmsg1 db "Bad commmand$"
errmsg2 db "Can't remove$"
errmsg3 db "Bad shift key$"
errmsg4 db "Not installed$"
errmsg5 db "Bad key speed$"
end_msg db 13,10,"$"
left_tag db "<Left>",0
right_tag db "<Right>",0
alt_tag db "<Alt>",0
ctrl_tag db "<Ctrl>",0
shift_tag db "<Shift>",0
commands db 'edksu?' ;Letters corrsponding to the
commands_end = $ ; command line switches.
jumptable:
dw offset enable ;Command routine jump table
dw offset disable
dw offset keyset
dw offset speedset
dw offset uninstall
dw offset display_help
shiftkeys db 'lracs' ;Letters corrsponding to the
shiftkeys_end = $ ; shift keys allowed.
other_seg dw 0 ;Segment of installed code
alrdy_installed db 0 ;bcopy already installed flag
remove_flag db 0 ;1 = uninstall
;========================================================================
; INITIALIZE
;========================================================================
initialize proc near
assume cs:code, ds:code
cld ;clear DF
mov ah,9 ;display copyright message
mov dx,offset program
int 21h
;------------------------------------------------------------------------
;See if a copy is already resident in memory.
;------------------------------------------------------------------------
mov word ptr [begin],0 ;initialize fingerprint
mov bx,0a000h ;Start at UMBs
mov ax,cs ;keep CS value in AX
find_copy:
inc bx ;increment search segment value
mov es,bx
cmp ax,bx ;not installed if current
je find_copy1 ; segment is looped back to
mov si,offset begin ;search this segment for ASCII
mov di,si ; fingerprint
mov cx,16
repe cmpsb
jne find_copy ;loop back if not found
inc alrdy_installed ;Clear installed flag
find_copy1:
mov other_seg,es ;save installed code segment
push cs ;ES = CS
pop es
assume es:code
;------------------------------------------------------------------------
;Parse the command line for switches.
;------------------------------------------------------------------------
mov si,offset command_tail ;point SI to command line text
xor cx,cx ;Clear high byte of CX
add cl,[si] ;Get length of command line.
jz parse_line_end ;If zero, skip parse routine
inc si
parse_line_loop:
lodsb ;Get byte
cmp al,'/' ;Look for command switch
je parse_line_skip ;If found, process command
loop parse_line_loop ;If not, keep looking
jmp short parse_line_end
parse_line_skip:
lodsb ;Get command
or al,20h ;Convert to lower case
push cx
mov di,offset commands ;Point to command letters
mov cx,offset commands_end - offset commands
mov bx,cx ;Save number of routines
repne scasb ;Find command letter
je command_found
add sp,2 ;Clean up stack
mov dx,offset errmsg1 ;Command not found msg
jmp short disp_error
command_found:
sub bx,cx ;Compute offset into table
pop cx ;Get back character count
dec bx
shl bx,1 ;Convert to word
push es
call [bx+offset jumptable]
pop es
jc disp_error ;Error if carry set.
loop parse_line_loop
parse_line_end:
;------------------------------------------------------------------------
;Construct and print Accel key message
;------------------------------------------------------------------------
mov di,offset keytag
mov es,other_seg
mov al,es:shift_mask ;Get shift key
mov ah,es:key_count ;Get key speed
push ax ;Save key speed value
push cs
pop es
mov bl,al ;See if specific to left
mov cl,4 ; or right keys.
shr bl,cl
test al,8
je accel_0
or bl,4
accel_0:
and al,07h
cmp al,bl ;Compare left and right
je accel_2 ; masks.
mov si,offset left_tag
ja accel_1
mov si,offset right_tag
accel_1:
call copy_str ;Copy Left/Right tag
accel_2:
or al,bl
mov si,offset alt_tag
test al,1
jne accel_3
mov si,offset ctrl_tag
test al,2
jne accel_3
mov si,offset shift_tag
accel_3:
call copy_str
pop ax ;Insert key speed value in
add ah,30h ; message
mov speedtag,ah
mov ah,9 ;Print message
mov dx,offset infomsg4
int 21h
;------------------------------------------------------------------------
;See if installed. If not, install.
;------------------------------------------------------------------------
cmp alrdy_installed,0 ;If not installed, install
je install
mov ax,4c00h ;Else, terminate with RC = 0.
int 21h
;------------------------------------------------------------------------
;Display error message and exit with Return Code = 1.
;------------------------------------------------------------------------
disp_error:
mov ah,9 ;Print string
int 21h
mov dx,offset end_msg
mov ah,9 ;Print CR,LF
int 21h
mov ax,4c01h ;Exit RC = 1
int 21h
;------------------------------------------------------------------------
;Install. Revector interrupts, Terminate and Stay Resident.
;------------------------------------------------------------------------
install:
mov ax,cs ;Copy code segment
mov word ptr [scanlist_ptr+2],ax ;Load segment into ptr
mov ax,3508h ;Set interrupt 8 (timer)
int 21h ; to the internal handler.
mov word ptr [int8h],bx
mov word ptr [int8h+2],es
mov ax,2508h
mov dx,offset timerint
int 21h
mov ax,3509h ;Set interrupt 9 (keyboard)
int 21h ; to the internal handler.
mov word ptr [int9h],bx
mov word ptr [int9h+2],es
mov ax,2509h
mov dx,offset keybint
int 21h
mov dx,offset infomsg3 ;Say program installed.
mov ah,9h
int 21h
mov dx,offset end_of_code ;Get pointer to the end of
add dx,15 ; code.
mov cl,4
shr dx,cl ;Convert to paragraphs
mov ax,3100h ;terminate with ERRORLEVEL = 0
int 21h ;Return to DOS.
initialize endp
;------------------------------------------------------------------------
; ENABLE activates the cursor speedup feature.
;------------------------------------------------------------------------
enable proc near
assume cs:code,ds:code
mov es,other_seg ;point to installed segment
mov es:enable_flag,1 ;Set enable flag
clc
ret
enable endp
;------------------------------------------------------------------------
; DISABLE deactivates the cursor speedup feature.
;------------------------------------------------------------------------
disable proc near
assume cs:code,ds:code
mov es,other_seg ;point to installed segment
mov es:enable_flag,0 ;Clear enable flag
clc
ret
disable endp
;------------------------------------------------------------------------
; SPEEDSET sets the number of keys pushed into the buffer per timer int
;------------------------------------------------------------------------
speedset proc near
assume cs:code,ds:code
speedset_loop:
jcxz speedset_err ;If EOL, error.
lodsb
dec cx
cmp al," "
jbe speedset_loop
sub al,30h ;Convert to hex
jbe speedset_err
cmp al,9
ja speedset_err
mov es,other_seg ;Get seg of installed code
mov es:key_count,al ;Set count
clc
speedset_exit:
ret
speedset_err:
mov dx,offset errmsg5 ;Bad key speed message
stc
jmp short speedset_exit
speedset endp
;------------------------------------------------------------------------
; KEYSET sets the shift key for acceleration of the cursor.
;------------------------------------------------------------------------
keyset proc near
assume cs:code,ds:code
mov dx,003fh ;Use DX as shift bit mask
keyset_loop:
mov al,[si] ;Get byte
cmp al,'/' ;If next switch, end.
je keyset_end
inc si
cmp al,' ' ;Check for a space.
jb keyset_end ;If non character, exit
ja keyset0 ;If not a space, process.
loop keyset_loop ;If at the end of the command
jmp short keyset5 ; line, end.
keyset0:
or al,20h ;Convert to lower case
mov di,offset shiftkeys ;Point to command letters
push cx ;Save command line count
mov cx,offset shiftkeys_end - offset shiftkeys
mov bx,cx ;Save number of keys
repne scasb ;Find shift key letter
je shiftkey_found ;If found, continue.
add sp,2 ;If not, Clean up stack.
mov dx,offset errmsg3 ;Not a proper shift key msg
stc ;Set carry and exit.
jmp short keyset_exit
shiftkey_found:
sub bx,cx ;Create index into keylist
dec bx ;Check for left and right
cmp bl,1 ;qualifiers, if so fix mask.
ja keyset2 ;Not left or right, continue
jb keyset1 ;Check for left qualifier
and dl,38h ;Right qualifier, Clear off
jmp short keyset4 ; left shift bits.
keyset1:
and dl,07h ;Left qualifier, Clear off
jmp short keyset4 ; right shift bits.
keyset2:
mov cl,bl ;Shift bits by the index into
sub cl,2 ; list of keys. This creates
mov bl,11h ; a mask compatible with the
shl bl,cl ; shift mask used in the int
cmp bl,44h ; routine.
jne keyset3 ;Fix mask if shift key
mov bl,0ch
keyset3:
and bl,dl ;Clear off bits for L/R
or dh,bl ;Add to shift mask
mov dl,3fh ;Reset left/right mask
keyset4:
pop cx ;Restore command line counter
loop keyset_loop ;Loop if not EOL
keyset5:
inc cx ;Fool loop instruction on ret
keyset_end:
or dh,dh ;Check for nul shift mask
jne keyset6 ;If zero, set unshiftable bit
mov dh,80h ; to disable.
keyset6:
mov es,other_seg ;point to installed segment
mov es:shift_mask,dh ;Set new shift mask
clc
keyset_exit:
ret
keyset endp
;------------------------------------------------------------------------
; DISPLAY HELP prints help message without installing.
;------------------------------------------------------------------------
display_help proc near
mov dx,offset infomsg1 ;point to help text.
stc ;Set flag to print message.
ret
display_help endp
;------------------------------------------------------------------------
; UNINSTALL deallocates the memory block ownded by the program and
; restores the interrupt vectors displaced on installation.
;------------------------------------------------------------------------
uninstall proc near
assume cs:code,ds:code
push cx ;Save command line count
cmp alrdy_installed,0 ;If not installed, don't
jne uninstall0 ; remove.
mov dx,offset errmsg4 ;Not installed msg
jmp short uninstall_exit
uninstall0:
mov cx,other_seg ;Get segment of installed prog
;
;Make sure the timer and keyboard vectors has not been altered.
;
mov ax,3508h ;check interrupt 8h vector
int 21h
mov ax,es
cmp cx,ax ;transfer segment to AX
jne uninstall_error
mov ax,3509h ;check interrupt 9h vector
int 21h
mov ax,es
cmp cx,ax ;transfer segment to AX
jne uninstall_error
;
;Restore interrupt 8 and 9 vectors.
;
mov es,cx ;Copy installed segment
push ds ;save DS
assume ds:nothing
lds dx,es:[int8h]
mov ax,2508h ;restore interrupt 8h vector
int 21h
lds dx,es:[int9h]
mov ax,2509h ;restore interrupt 9h vector
int 21h
pop ds ;restore DS
assume ds:code
;
;Release the memory occupied by the program.
;
mov ah,49h ;Free memory given to
int 21h ; original program block
jc uninstall_error ;jmp if error
cmp es:environment_flg,0 ;See if environment still
je uninstall1 ; owned by resident code.
push es
mov es,es:env_seg ;Get segment of environment
mov ah,49h ;Deallocate environment seg
int 21h
pop es
jc uninstall_error ;Jmp if error
uninstall1:
;
;Destroy the ASCII fingerprint that identifies the code and exit.
;
not word ptr es:[begin] ;destroy fingerprint
mov dx,offset infomsg2 ;Say program removed.
uninstall_exit:
stc ;Set flag to end program
pop cx
ret ;exit
;
;The program can't be uninstalled. Point to error message and exit.
;
uninstall_error:
mov dx,offset errmsg2 ;Remove error message
jmp short uninstall_exit
uninstall endp
;------------------------------------------------------------------------
; CHECKVECTOR is called by REMOVE to compare the segment pointed to by an
; interrupt vector against a segment value supplied by the caller.
; Entry: AL - interrupt number
; Exit: ZF clear - segments do not match
; ZF set - segments match
;------------------------------------------------------------------------
checkvector proc near
push es
pop cx
mov ah,35h ;get vector
int 21h
mov ax,es ;transfer segment to AX
cmp ax,cx ;compare
ret
checkvector endp
;------------------------------------------------------------------------
; COPYSTR Copies an ASCIIZ string
; Entry: SI - Ptr to source ASCIIZ string
; DI - Ptr to destination buffer
;------------------------------------------------------------------------
copy_str proc near
push ax
copy_str_1:
lodsb
or al,al
je copy_str_2
stosb
jmp short copy_str_1
copy_str_2:
pop ax
ret
copy_str endp
code ends
end begin